<template>
  <view :id="id" class="tn-scroll-list">
    <!-- 滑动区域 -->
    <scroll-view
      class="tn-scroll-list__scroll-view"
      scroll-x
      :upper-threshold="0"
      :lower-threshold="0"
      @scroll="handleScroll"
      @scrolltoupper="handleScrollToUpper"
      @scrolltolower="handleScrollToLower"
    >
      <!-- 内容 -->
      <view class="tn-scroll-list__content">
        <slot></slot>
      </view>
    </scroll-view>

    <!-- 指示器 -->
    <view
      v-if="indicator"
      class="tn-scroll-list__indicator"
    >
      <view :id="`${id}_ind`" class="line" :class="[indicatorClass]" :style="indicatorStyle">
        <view :id="`${id}_bar`" class="bar" :class="[indicatorBarClass]" :style="indicatorBarStyle"></view>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
import { scrollListProps, scrollListEmits } from '../../../types/tn-scroll-list'
import { ColorInfo } from '../../../types/tuniao-ui'
import { computed, CSSProperties, getCurrentInstance, ComponentInternalInstance, ref, reactive, onMounted, nextTick } from 'vue'
import useComponentColor from '../../../libs/hooks/useComponentColor'
import { handleValueWithUnit, uuid, getRectInfo } from '../../../utils'

const props = defineProps(scrollListProps)
const emits = defineEmits(scrollListEmits)

const { splitColorInfo } = useComponentColor()
// 解析指示器颜色
const indicatorColor = computed<ColorInfo>(() => {
  return splitColorInfo('bg', props?.indicatorColor || '')
})
// 解析指示器滑块颜色
const indicatorBarColor = computed<ColorInfo>(() => {
  return splitColorInfo('bg', props?.indicatorbarColor || '')
})


// 指示器样式
const indicatorStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (indicatorColor.value.type === 'style') {
    style.backgroundColor = indicatorColor.value.value
  }
  if (props?.indicatorWidth) {
    style.width = handleValueWithUnit(props.indicatorWidth)
  }
  return Object.assign(style, props?.customStyle || {})
})
// 指示器滑块样式
const indicatorBarStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (indicatorBarColor.value.type === 'style') {
    style.backgroundColor = indicatorBarColor.value.value
  }
  if (props?.indicatorBarWidth) {
    style.width = handleValueWithUnit(props.indicatorBarWidth)
  }
  
  // 滑块位置计算
  const barMoveWidth: number = indicatorRectWidth.value - indicatorBarRectWidth.value
  const x = (scrollInfo.scrollLeft / (scrollInfo.scrollWidth - scrollViewWidth.value)) * barMoveWidth
  style.transform = `translateX(${x}px)`
  return style
})

// 指示器对应的类
const indicatorClass = computed<string>(() => {
  let clazz: string[] = []
  if (indicatorColor.value.type === 'class') {
    clazz.push(indicatorColor.value.value)
  }
  return clazz.join(' ')
})
// 指示器滑块对应的类
const indicatorBarClass = computed<string>(() => {
  let clazz: string[] = []
  if (indicatorBarColor.value.type === 'class') {
    clazz.push(indicatorBarColor.value.value)
  }
  return clazz.join(' ')
})


const instance = getCurrentInstance() as ComponentInternalInstance
const id: string = uuid()
// ScrollView滑动位置信息
let scrollInfo = reactive<{
  scrollLeft: number,
  scrollWidth: number
}>({
  scrollLeft: 0,
  scrollWidth: 0
})
// 滑动区域的宽度
let scrollViewWidth = ref<number>(0)
// 指示器和滑块的宽度信息
let indicatorRectWidth = ref<number>(0)
let indicatorBarRectWidth = ref<number>(0)

// 初始化组件, 获取内容的宽度
let getRectCount: number = 0
const init = async () => {
  await initComponent()
  await initIndicator()
}
const initIndicator = async () => {
  // 如果不显示指示器则跳过
  if (!props?.indicator) return
  // 获取指示器信息
  const rect = await getRectInfo(`#${id}_ind`, instance)
  const barRect = await getRectInfo(`#${id}_bar`, instance)
  if (!rect || !barRect) {
    if (getRectCount > 10) {
      console.error('[tn-scroll-list]获取指示器信息失败')
      return
    }
    setTimeout(() => {
      initIndicator()
      getRectCount++
    }, 50);
    return
  }
  getRectCount = 0
  indicatorRectWidth.value = rect.width || 0
  indicatorBarRectWidth.value = barRect.width || 0
}
const initComponent = async () => {
  // 获取内容的宽度
  const rect = await getRectInfo(`#${id}`, instance)
  if (!rect) {
    if (getRectCount > 10) {
      console.error('[tn-scroll-list]获取内容的宽度信息失败')
      return
    }
    setTimeout(() => {
      initComponent()
      getRectCount++
    }, 50);
    return
  }

  getRectCount = 0
  scrollViewWidth.value = rect.width || 0
}

// 处理scroll-view滚动事件
const handleScroll = (e: any) => {
  scrollInfo.scrollLeft = e.detail.scrollLeft
  scrollInfo.scrollWidth = e.detail.scrollWidth
}
// 处理滑动到最左边触发的事件
const handleScrollToUpper = () => {
  emits('left')
  scrollInfo.scrollLeft = 0
}
// 处理滑动到最右边触发的事件
const handleScrollToLower = () => {
  emits('right')
}

onMounted(() => {
  nextTick(() => {
    setTimeout(() => {
      init()
    }, 50);
  })
  
})
</script>

<script lang="ts">
export default {
  options: {
    // 在微信小程序中将组件节点渲染为虚拟节点，更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
    virtualHost: true
  }
}
</script>

<style lang="scss" scoped>
@import '../../../theme.scss';

.tn-scroll-list {
  position: relative;

  &__indicator {
    display: flex;
    flex-direction: row;
    justify-content: center;
    margin-top: 30rpx;
    
    .line {
      width: 120rpx;
      height: 8rpx;
      border-radius: 200rpx;
      overflow: hidden;
      background-color: #E6E8E6;
    }
    .bar {
      width: 40rpx;
      height: 8rpx;
      border-radius: 200rpx;
      background-color: $tn-main-color;
    }
  }
}
</style>
